Skip to main content

06 Before or After and OCC

Before or After

系统允许并发执行;但并发执行得到的结果和串行执行相同。

global lock

任何时间,只有一个事务允许执行,相当于串行。

fine-grained locking

希望锁越多越好,不同的数据对应不同的锁。同一数据串行,不同数据并行。

然而,这种细粒度控制仍然可能出现race condition等问题。

2PL

拿锁和放锁分为两个阶段。具体来说,开始放锁之后,就不允许新拿到任何锁。

可串行化

  • 视图可串行化
    • 每个读取的初始值相同
    • 每个读操作依赖同一个写操作
    • 最终每个写操作来自同一个事务
  • 冲突可串行化
    • 不同事务操作同一数据,且有一个是写操作,即冲突
    • 通过图来判断,无环则可串行
  • 顺序一致性

冲突可串行化属于视图可串行化。判断是否为视图可串行化属于NP hard问题。

幻影问题

在遍历同时插入,可能会导致冲突;只给具体的数据加锁无法解决这个问题。

理论上可以用谓词锁解决;任何两个冲突的操作都需要加锁。但实际上,这种问题一般被无视。

OCC

  • 并发本地处理
    • 将数据读到读集合中
    • 将数据写到buffer中
  • 在临界区验证可串行化
  • 提交/中止

不同的事务可能对数据进行相同的修改,因此要引入版本号。

  • phase 1
    • 将数据读到读集合中:同时读数据和版本号
    • 将数据写到buffer中:更新write后还需要更新read
  • phase 2 验证可串行化:通过版本号确认是否改变
  • phase 3
    • 如果read-set中的数据被修改/上锁,中止
    • 提交

phase2和3不能拆开。

OCC可以避免2PL的问题。由于在操作全部执行后才提交,OCC可以将拿锁顺序排序,避免2PL的死锁。此外,OOC还可以将read-set的锁去掉。